package com.xujie.sportsmeeting.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xujie.sportsmeeting.common.result.Result;
import com.xujie.sportsmeeting.dto.EventDTO;
import com.xujie.sportsmeeting.dto.EventQueryDTO;
import com.xujie.sportsmeeting.entity.CompetitionEvent;
import com.xujie.sportsmeeting.entity.Judge;
import com.xujie.sportsmeeting.service.CompetitionEventService;
import com.xujie.sportsmeeting.service.JudgeService;
import com.xujie.sportsmeeting.service.EventJudgeService;
import com.xujie.sportsmeeting.vo.EventVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.List;

/**
 * 比赛项目管理控制器
 */
@Tag(name = "比赛项目管理", description = "比赛项目管理相关接口")
@RestController
@RequestMapping("/event")
@RequiredArgsConstructor
public class EventController {

    private final CompetitionEventService competitionEventService;
    private final JudgeService judgeService;
    private final EventJudgeService eventJudgeService;

    @Operation(summary = "获取比赛项目列表")
    @GetMapping("/list")
    @PreAuthorize("hasAnyAuthority('event', 'system:user', 'athlete') or authentication.name == 'admin'")
    public Result<IPage<EventVO>> getEventList(EventQueryDTO queryDTO) {
        Page<CompetitionEvent> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        LambdaQueryWrapper<CompetitionEvent> wrapper = new LambdaQueryWrapper<>();
        
        // 构建查询条件
        if (StringUtils.hasText(queryDTO.getKeyword())) {
            wrapper.like(CompetitionEvent::getEventName, queryDTO.getKeyword())
                   .or().like(CompetitionEvent::getEventCode, queryDTO.getKeyword())
                   .or().like(CompetitionEvent::getVenue, queryDTO.getKeyword());
        }
        
        if (queryDTO.getEventType() != null) {
            wrapper.eq(CompetitionEvent::getEventType, queryDTO.getEventType());
        }
        
        if (queryDTO.getGenderLimit() != null) {
            wrapper.eq(CompetitionEvent::getGenderLimit, queryDTO.getGenderLimit());
        }
        
        if (queryDTO.getAgeGroup() != null && !queryDTO.getAgeGroup().isEmpty()) {
            wrapper.eq(CompetitionEvent::getAgeGroup, queryDTO.getAgeGroup());
        }
        
        if (queryDTO.getUnit() != null && !queryDTO.getUnit().isEmpty()) {
            wrapper.eq(CompetitionEvent::getUnit, queryDTO.getUnit());
        }
        
        if (queryDTO.getStatus() != null) {
            wrapper.eq(CompetitionEvent::getStatus, queryDTO.getStatus());
        }
        
        wrapper.orderByDesc(CompetitionEvent::getCreateTime);
        
        Page<CompetitionEvent> result = competitionEventService.page(page, wrapper);
        
        // 转换为VO
        IPage<EventVO> voPage = result.convert(event -> {
            EventVO vo = new EventVO();
            BeanUtils.copyProperties(event, vo);
            // 加载分配的裁判员信息
            vo.setAssignedJudges(eventJudgeService.getJudgesByEventId(event.getId()));
            return vo;
        });
        
        return Result.success(voPage);
    }

    @Operation(summary = "获取比赛项目详情")
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('event') or authentication.name == 'admin'")
    public Result<EventVO> getEventDetail(@PathVariable Long id) {
        CompetitionEvent event = competitionEventService.getById(id);
        if (event == null) {
            return Result.error("比赛项目不存在");
        }
        
        EventVO vo = new EventVO();
        BeanUtils.copyProperties(event, vo);
        
        return Result.success(vo);
    }

    @Operation(summary = "获取比赛项目简单列表（用于下拉选择）")
    @GetMapping("/simple")
    @PreAuthorize("hasAnyAuthority('event', 'system:user', 'athlete') or authentication.name == 'admin'")
    public Result<List<EventVO>> getEventListSimple(@RequestParam(required = false) Integer status) {
        LambdaQueryWrapper<CompetitionEvent> wrapper = new LambdaQueryWrapper<>();
        
        if (status != null) {
            wrapper.eq(CompetitionEvent::getStatus, status);
        }
        
        wrapper.orderByDesc(CompetitionEvent::getCreateTime);
        
        List<CompetitionEvent> events = competitionEventService.list(wrapper);
        
        // 转换为简单VO
        List<EventVO> eventVOs = events.stream().map(event -> {
            EventVO vo = new EventVO();
            vo.setId(event.getId());
            vo.setEventName(event.getEventName());
            vo.setEventCode(event.getEventCode());
            vo.setStatus(event.getStatus());
            return vo;
        }).toList();
        
        return Result.success(eventVOs);
    }

    @Operation(summary = "创建比赛项目")
    @PostMapping
    @PreAuthorize("hasAuthority('event:add') or authentication.name == 'admin'")
    public Result<Void> createEvent(@Valid @RequestBody EventDTO eventDTO) {
        // 检查项目编码是否存在
        if (competitionEventService.existsByEventCode(eventDTO.getEventCode())) {
            return Result.error("项目编码已存在");
        }
        
        CompetitionEvent event = new CompetitionEvent();
        BeanUtils.copyProperties(eventDTO, event);
        
        competitionEventService.save(event);
        return Result.success("比赛项目创建成功");
    }

    @Operation(summary = "更新比赛项目信息")
    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('event:edit') or authentication.name == 'admin'")
    public Result<Void> updateEvent(@PathVariable Long id, @Valid @RequestBody EventDTO eventDTO) {
        CompetitionEvent existEvent = competitionEventService.getById(id);
        if (existEvent == null) {
            return Result.error("比赛项目不存在");
        }
        
        // 检查项目编码是否被其他项目使用
        CompetitionEvent eventWithSameCode = competitionEventService.findByEventCode(eventDTO.getEventCode());
        if (eventWithSameCode != null && !eventWithSameCode.getId().equals(id)) {
            return Result.error("项目编码已被其他项目使用");
        }
        
        CompetitionEvent event = new CompetitionEvent();
        BeanUtils.copyProperties(eventDTO, event);
        event.setId(id);
        
        competitionEventService.updateById(event);
        return Result.success("比赛项目更新成功");
    }

    @Operation(summary = "删除比赛项目")
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('event:delete') or authentication.name == 'admin'")
    public Result<Void> deleteEvent(@PathVariable Long id) {
        CompetitionEvent event = competitionEventService.getById(id);
        if (event == null) {
            return Result.error("比赛项目不存在");
        }
        
        competitionEventService.removeById(id);
        return Result.success("比赛项目删除成功");
    }

    @Operation(summary = "批量删除比赛项目")
    @DeleteMapping("/batch")
    @PreAuthorize("hasAuthority('event:delete') or authentication.name == 'admin'")
    public Result<Void> batchDeleteEvents(@RequestBody List<Long> ids) {
        competitionEventService.removeByIds(ids);
        return Result.success("批量删除成功");
    }

    @Operation(summary = "启用/禁用比赛项目")
    @PutMapping("/{id}/status")
    @PreAuthorize("hasAuthority('event:edit') or authentication.name == 'admin'")
    public Result<Void> toggleEventStatus(@PathVariable Long id, @RequestBody StatusRequest request) {
        CompetitionEvent event = competitionEventService.getById(id);
        if (event == null) {
            return Result.error("比赛项目不存在");
        }
        
        event.setStatus(request.getStatus());
        competitionEventService.updateById(event);
        
        String statusText = request.getStatus() == 1 ? "启用" : "禁用";
        return Result.success("比赛项目" + statusText + "成功");
    }

    @Operation(summary = "获取项目分配的裁判员")
    @GetMapping("/{id}/judges")
    @PreAuthorize("hasAuthority('event') or authentication.name == 'admin'")
    public Result<List<Judge>> getEventJudges(@PathVariable Long id) {
        List<Judge> judges = eventJudgeService.getJudgesByEventId(id);
        return Result.success(judges);
    }

    @Operation(summary = "为项目分配裁判员")
    @PostMapping("/{id}/judges")
    @PreAuthorize("hasAuthority('event:edit') or authentication.name == 'admin'")
    public Result<Void> assignJudgesToEvent(@PathVariable Long id, @RequestBody JudgeAssignRequest request) {
        CompetitionEvent event = competitionEventService.getById(id);
        if (event == null) {
            return Result.error("比赛项目不存在");
        }

        // 验证裁判员是否存在
        for (Long judgeId : request.getJudgeIds()) {
            Judge judge = judgeService.getById(judgeId);
            if (judge == null) {
                return Result.error("裁判员ID " + judgeId + " 不存在");
            }
        }

        // 分配裁判员到项目
        boolean success = eventJudgeService.assignJudgesToEvent(id, request.getJudgeIds());
        if (success) {
            return Result.success("裁判员分配成功");
        } else {
            return Result.error("裁判员分配失败");
        }
    }

    @Operation(summary = "移除项目的裁判员分配")
    @DeleteMapping("/{id}/judges")
    @PreAuthorize("hasAuthority('event:edit') or authentication.name == 'admin'")
    public Result<Void> removeJudgesFromEvent(@PathVariable Long id, @RequestBody JudgeAssignRequest request) {
        CompetitionEvent event = competitionEventService.getById(id);
        if (event == null) {
            return Result.error("比赛项目不存在");
        }

        // 移除项目的裁判员分配
        boolean success = eventJudgeService.removeJudgesFromEvent(id, request.getJudgeIds());
        if (success) {
            return Result.success("裁判员移除成功");
        } else {
            return Result.error("裁判员移除失败");
        }
    }

    // 内部请求类
    public static class StatusRequest {
        private Integer status;
        
        public Integer getStatus() {
            return status;
        }
        
        public void setStatus(Integer status) {
            this.status = status;
        }
    }

    public static class JudgeAssignRequest {
        private List<Long> judgeIds;
        
        public List<Long> getJudgeIds() {
            return judgeIds;
        }
        
        public void setJudgeIds(List<Long> judgeIds) {
            this.judgeIds = judgeIds;
        }
    }
}
